﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
using FasterWPF;

namespace FasterWPF
{
    public class GridComposite: IComposite
    {
        public bool IsGrid()
        {
            return true;
        }

        public void RemoveFromChain(Border bdr) //unhook all the children so they may be re-added later, if desired
        {
            GetContainer<Grid>(bdr).Children.Clear();
        }

        public C GetContainer<C>(Border bdr)
            where C: FrameworkElement
        {
           return ((C)(((ContentControl)(bdr.Child)).Content));
        }

        public C GetContainerFromChildContentControl<C>(ContentControl chain) where C : FrameworkElement
        {
           return ((C)(chain.Content));
        }

        public void ShowGridLines(System.Windows.Controls.ContentControl chain)
        {
            ((Grid)(chain.Content)).ShowGridLines = true;
        }

        public T GetParent<T>(ContentControl sender)
              where T : FrameworkElement
        {
            return (T)((ContentControl)sender).GetParentFromContentControlOfComposite<T>();
        }

        public Panel AddChild<T>(T source, System.Windows.Controls.ContentControl chain, int row, int col, System.Windows.FrameworkElement child)
               where T : FrameworkElement
        {
            Grid g = ((Grid)(chain.Content));
            g.Children.Add(child);
            Grid.SetColumn(child, col);
            Grid.SetRow(child, row);

            return (Panel)g;
        }

        public void AddCompositeToContentControl<T>(T chain, ContentControl contentControl, object settings)
            where T: FrameworkElement
        {
            Grid g = new Grid();
            GridSettings gs = null;

            if (settings != null)
            {
                gs = (settings as GridSettings);
            }
            else
            {
                if (SettingsManager.ContainsSetting<T>(chain, "GridSettings"))
                {
                    gs = SettingsManager.GetSetting<T, GridSettings>(chain, "GridSettings");
                }
                else
                {
                    //no default settings
                    throw new Exception("Composite Grid Dimensions must be defined on Parent T.");
                }
            }
            applyGridSettings(gs, g);

            contentControl.Content = g;
        }

        private static Grid applyGridSettings(GridSettings gridSet, Grid g)
        {
            if (gridSet.Height != null)
            {
                g.Height = gridSet.Height;
            }

            if (gridSet.Width != null)
            {
                g.Width = gridSet.Width;
            }

            if (gridSet.RowHeights != null)
            {
                IterHelpers.ApplyLoop(gridSet.NumRows, (i =>
                {
                    RowDefinition r = new RowDefinition() { MinHeight = 10D };
                    if (((double)gridSet.RowHeights[i]).ToString() != double.NaN.ToString())
                    {                       
                        r.Height = new GridLength(gridSet.RowHeights[i],
        gridSet.RowUnitTypes[i]);
                        g.RowDefinitions.Add(r);
                    }
                }));
            }
            else
            {
                IterHelpers.ApplyLoop(gridSet.NumRows, (i =>
                {
                    g.RowDefinitions.Add(new RowDefinition() { MinHeight = 10D });
                }));
            }
                    
            IterHelpers.ApplyLoop(gridSet.NumColumns, (i =>
            {
                ColumnDefinition c = new ColumnDefinition() { MinWidth = 10D };
                if (((double)gridSet.ColWidths[i]).ToString() != double.NaN.ToString())
                {
                    c.Width = new GridLength(gridSet.ColWidths[i],
    gridSet.ColUnitTypes[i]);
                    g.ColumnDefinitions.Add(c);
                }
            }));

            return g;
        }

        public T GetParentFromChild<T>(FrameworkElement childElement) where T : FrameworkElement
        {
            return (T)((ContentControl)((Grid)((FrameworkElement)childElement.Parent)).Parent).GetParentFromContentControlOfComposite<T>();
        }

        public System.Windows.Controls.Border GetBorder<T>(System.Windows.FrameworkElement childElement)
        {
            return (Border)((Grid)((FrameworkElement)childElement).Parent).Parent.Cast<ContentControl>().Parent;
        }
        
        public K Get<K, T>(System.Windows.Controls.ContentControl chain, int row, int column)
                where K : UIElement
                where T : FrameworkElement
        {
        K label = default(K);

               foreach (UIElement uie in ((Grid)(chain.Content)).Children)
                    {
                        int currentRowNum = Grid.GetRow(uie);
                        if (currentRowNum == row)
                        {
                            int currentColNum = Grid.GetColumn(uie);
                            if (currentColNum == column)
                            {
                                if (uie is K)
                                {
                                    label = (K)uie;
                                }
                            }
                        }
                    }

            return label;
        }

        public UIElementCollection GetChildren(object container)
        {
            return (container as Grid).Children;
        }
    }
}
